#include "PSSwitch.h"
int fd = -1;
//************************************
// Method:    	tPSSwitch				判断站状态为主站或从站
// Programmer:  lww
// Time:		2018/12/22
// Returns:   	void *
// Parameter: 	void * arg
//************************************
void *tPSSwitch(void* arg)
{
#define MAX_JUDGE_NUM	10				//< 最大失误判断次数
#define DELAY_MS	100					//< 每轮串口工作延时时间（ms）
#define PORT_SENDandRECV_WAIT_MS	100	//< 最大等待串口收发时间（ms）即串口接收和发送的超时

	int i;

	char tmp_char;
	int count = 0;

	printf("the Kernel_%s is %d\r\n", "tPSSwitch_ID", syscall(SYS_gettid));				//< duan20200610
	//< 初始化串口
	//< 参数一：打开串口的设备描述符
	//< 参数二：属性设置，依次为：
	//< 		O_RDWR——读写打开
	//<			O_NOCTTY——如果设备描述符指的是终端设备，则不将此设备分配作为此进程的控制终端(可以告诉Linux这个程序不会成为这个端口上的“控制终端”.如果不这样做的话,所有的输入,比如键盘上过来的Ctrl+C中止信号等等,会影响到你的进程。)
	//<			O_NDELAY——告诉Linux,这个程序并不关心DCD信号线的状态——也就是不关心端口另一端是否已经连接(非阻塞)
	if ((fd = Port_Open(PORT_PSSWITCH, true, O_RDWR | O_NOCTTY | O_NDELAY, B9600, CS8, 0, 1)) < 0)
	{
		perror(PORT_PSSWITCH);
		printf("Open failed\r\n");
		return NULL;
	}
	ExactDelay(5000);
	/*
		初次上电判断主从站身份:
		如接收到消息，则主站已存在，判定当前身份为从站;
		如果连续多次未收到消息，则判定没有站存在，当前站为主站;
	*/
	for (i = 0; i < MAX_JUDGE_NUM; i++)
	{
		ExactDelay(200);
		int PortRecvLength = Port_Recv(fd, &tmp_char, 1, PORT_SENDandRECV_WAIT_MS, true);
		Clear_Port_Register(fd, CLEAR_IN);/*清空串口接收缓存区*/
		printf("Start recv: %u\n", tmp_char);
		if (PortRecvLength < 1)
		{
			printf("PSSwitch: Recv wrong in first time\r\n");
			continue;
		}
		else
		{
			SYS_Role_Turn(Slave_Role);
			break;
		}
		//else if(tmp_char== MASTER_RUN)
		//{
		//	SYS_Role_Turn(Slave_Role);
		//	break;
		//}
		//else {
		//	Clear_Port_Register(fd, CLEAR_IN);/*清空串口接收缓存区*/
		//	i--;
		//}
	}
	if (SYS_Role != Slave_Role)
		SYS_Role_Turn(Master_Alone_Role);




	pthread_t tPSSwitchSend = 0;
	char name[14] ="tPSSwitchSend";
	THREAD_CREATE_FAILED(Thread_Create(name, &tPSSwitchSend, NULL, SCHED_POLICY, 89, true, tPSSwitchSend_Thread, CONTROL_CORE, NULL));





	//< 实时主从切换判断
	while (1)
	{
		ExactDelay(100);
		/*
			从站一直接收主站消息:
			如果接收失败并累计够一定次数，则连续发送几次“从站切换为主站”信号，并进行身份切换;
			如果接收成功，则向主站发送从站在运行的信号;
		*/
		if (SYS_Role == Slave_Role)
		{
			//tmp_char = SLAVE_RUN;
			//Port_Send(fd, &tmp_char, 1, PORT_SENDandRECV_WAIT_MS, true);
			//Clear_Port_Register(fd, CLEAR_OUT);/*清空串口发送缓存区*/
			int PortRecvLength = Port_Recv(fd, &tmp_char, 1, PORT_SENDandRECV_WAIT_MS, true);
			Clear_Port_Register(fd, CLEAR_IN);/*清空串口接收缓存区*/
			if (PortRecvLength < 1)
			{
				count++;
				if (count < MAX_JUDGE_NUM)
					continue;
				for (i = 0; i < MAX_JUDGE_NUM; i++)
				{
					tmp_char = SLAVE_TRUE_MASTER;
					Port_Send(fd, &tmp_char, 1, PORT_SENDandRECV_WAIT_MS, true);
				}
				SYS_Role_Turn(Master_Alone_Role);
				count = 0;
				continue;
			}
			else
			{
				if (tmp_char!= MASTER_RUN) {
					printf("Slave recv:%u\n", tmp_char);
				}
				count = 0;
				//if ((tmp_char==SLAVE_RUN) && (IPTail_Num < MASTER_SLAVE_ID_DT))
				//{
				//	SYS_Role_Turn(Master_Twins_Role);
				//	continue;
				//}
			}

		}
		/*
			主站接收从站消息：
			如果多次未接收到从站消息，则判定为从站离线；
			如果接收到从站消息，但是从站发送的消息为主站应该发送的消息，则表明此时两方身份都判定为了主站，则站号较大的切换为从站；
			如果接收到从站运行消息，且当前主站判定从站是不存在的，则切换状态为主站且从站存在；
			发送信息给从站
		*/
		else if (SYS_Role == Master_Alone_Role || SYS_Role == Master_Twins_Role)
		{
			/*tmp_char = MASTER_RUN;
			Port_Send(fd, &tmp_char, 1, PORT_SENDandRECV_WAIT_MS, true);*/
			//Clear_Port_Register(fd, CLEAR_OUT);/*清空串口发送缓存区*/
			int PortRecvLength = Port_Recv(fd, &tmp_char, 1, PORT_SENDandRECV_WAIT_MS, true);
			Clear_Port_Register(fd, CLEAR_IN);/*清空串口接收缓存区*/
			if (PortRecvLength < 1)
			{
				count++;
				if (count >= MAX_JUDGE_NUM)
				{
					count = MAX_JUDGE_NUM;
					if (SYS_Role == Master_Twins_Role)
						SYS_Role_Turn(Master_Alone_Role);
				}
			}
			else
			{
				if (tmp_char!= SLAVE_RUN) {
					printf("Master recv:%u\n", tmp_char);
				}
				count = 0;
				if ((tmp_char == MASTER_RUN || tmp_char == SLAVE_TRUE_MASTER) && (IPTail_Num > MASTER_SLAVE_ID_DT))
				{
					SYS_Role_Turn(Slave_Role);
					continue;
				}					
				else if (tmp_char == SLAVE_RUN)
				{
					if (SYS_Role == Master_Alone_Role)
						SYS_Role_Turn(Master_Twins_Role);
				}
			}
		}
	}

	

#undef MAX_JUDGE_NUM
#undef DELAY_MS
#undef PORT_SENDandRECV_WAIT_MS






#define Server_port 9501
#define Client_port 9502
#define Station16_IP "192.166.2.1"
#define Station66_IP "192.166.2.2"
#define Station_Servet_IP ((IPTail_Num <MASTER_SLAVE_ID_DT) ? (Station16_IP) : (Station66_IP)) 
#define Station_Client_IP ((IPTail_Num >MASTER_SLAVE_ID_DT) ? (Station16_IP) : (Station66_IP)) 
    int sock=-1;       //全局变量
	int sock_accept=-1;//全局变量
	pthread_t tPSSwitchSend = 0;
	pthread_t tPSSwitchRecv = 0;
	char name[14]  = "tPSSwitchSend";
	char name1[14] = "tPSSwitchRecv";

	if (SYS_Role == Master_Alone_Role || SYS_Role == Master_Twins_Role) {
		if (false == TCP_Sever_Init(&sock, Server_port, 0, Station_Servet_IP)) {
			printf("PSSwitch sever-sock init wrong\r\n");
		}
	
	    while (1){
		    if (false == TCP_Sever_Accept(&sock, &sock_accept, 5)){
			    ExactDelay(100);
			    continue;
		    }
		    else {
			    break;
		    }
        }
	}
	THREAD_CREATE_FAILED(Thread_Create(name, &tPSSwitchSend, NULL, SCHED_POLICY, 89, true, tPSSwitchSend_Thread, CONTROL_CORE, NULL));
	THREAD_CREATE_FAILED(Thread_Create(name1, &tPSSwitchRecv, NULL, SCHED_POLICY, 89, true, tPSSwitchRecv_Thread, CONTROL_CORE, NULL));

	while (1) {
		RoughDelay_S(10000);
	}
	return;



#undef Server_port
#undef Client_port 
#undef Station16_IP
#undef Station66_IP

}


void* tPSSwitchSend_Thread(void* arg) {
#define MAX_JUDGE_NUM	5				//< 最大失误判断次数
#define DELAY_MS	50					//< 每轮串口工作延时时间（ms）
#define PORT_SENDandRECV_WAIT_MS	100	//< 最大等待串口收发时间（ms）即串口接收和发送的超时
	//int* fd1 = (int*)arg;
	//int fd=*fd1;

	int i;
	char tmp_char;
	//< 实时主从切换判断
	while (1)
	{
		ExactDelay(1000);
		if (SYS_Role == Slave_Role)
		{
			tmp_char = SLAVE_RUN;
			Port_Send(fd, &tmp_char, 1, 1000, true);
			ExactDelay(200);
			Clear_Port_Register(fd, CLEAR_OUT);/*清空串口发送缓存区*/
		}
		else if (SYS_Role == Master_Alone_Role || SYS_Role == Master_Twins_Role)
		{
			tmp_char = MASTER_RUN;
			Port_Send(fd, &tmp_char, 1, 1000, true);
			ExactDelay(200);
			Clear_Port_Register(fd, CLEAR_OUT);/*清空串口发送缓存区*/
		}
	}



#undef MAX_JUDGE_NUM
#undef DELAY_MS
#undef PORT_SENDandRECV_WAIT_MS
}

void* tPSSwitchRecv_Thread(void* arg) {

}









//************************************
// Method:    	BakData_ANA				从站解析备份文件
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	bool					true:接收字节数正确；false：错误
// Parameter: 	void * Data				数据区头指针
// Parameter: 	int len					数据包长度
// Parameter: 	short Head				报头
// Parameter: 	short Tail				报尾
//************************************
bool BakData_ANA(void* Data, int len, short Head, short Tail)
{
#define MEMREAD1(var)	MEMREAD(var, Data)
#define WRONG_DEAL	{\
	printf("Analyze PSS data wrong!\r\n");\
	return false;\
}

	int _iLen = 0;
	short status = 0;
	short tmp_short;
	short ptr_off;

		//< 校验报头
	MEMREAD1(tmp_short);
	if (tmp_short != Head)
		WRONG_DEAL;

	//< 读出当前指针到报尾的指针的距离，校验报尾
	MEMREAD1(ptr_off);
	memcpy(&tmp_short, (char*)(Data)+ptr_off, sizeof(tmp_short));
	if (tmp_short != Tail)
		WRONG_DEAL;

	//< 状态
	MEMREAD1(status);

	if (_iLen != (int)(len - sizeof(tmp_short)))
		WRONG_DEAL;
	return true;

#undef WRONG_DEAL
#undef MEMREAD1
}


//************************************
// Method:    	tRecvBak				从站接收备份线程
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void *
// Parameter: 	void * arg
//************************************
void *tRecvPSS(void* arg)
{
#define PACK_MAXNUM	8

	int sock;
	short Head = 2601;				//< 报头
	short Tail = 3420;				//< 报尾
	char Data2Recv[PACK_MAXNUM];	//< 存放数据包的数组
	short len;

	printf("the Kernel_%s is %d\r\n", "tRecvBak_ID", syscall(SYS_gettid));			//< duan20200610
	//< 初始化UDP设置
	if (false == UDP_Init(&sock, 9502, 0, 0, UDP_RECV_STATUS, nullptr)) { return 0; }

	while (1)
	{

		if (SYS_Role == Slave_Role)
		{
			//< 接收数据
			memset(Data2Recv, 0, sizeof(Data2Recv));
			len = (short)UDP_Recv_Any_Bytes(&sock, Data2Recv, PACK_MAXNUM);
			if (len == -1)
				continue;
			//< 解析报文
			if (Slave_Role == SYS_Role)																							//< duan1005
				BakData_ANA(Data2Recv, len, Head, Tail);
		}
		else
			RoughDelay_S(2);

	}
	close(sock);//< 断开连接

#undef PACK_MAXNUM
}


//************************************
// Method:    	BakData_PACK_Make			备份文件打包程序
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	int							打包长度
// Parameter: 	void * Data					数据包头指针
// Parameter: 	short Head					报头
// Parameter: 	short Tail					报尾
// Parameter: 	int Limit_Len				单次数据包长度限制
// Parameter: 	short * SaveModel_Num		存储的模块的数量
//************************************
int BakData_PACK_Make(void* Data, short Head, short Tail, short* SaveModel_Num)
{
#define MEMWRITE1(name)	MEMWRITE(name, Data);
	int _iLen = 0;
	short tmp_short = 0;
	/*static int i = 0;*/					//< duan20200503注释
	void* Data1 = NULL;
	int Model_ID, Model_Type;

	//< 报头
	MEMWRITE1(Head);

	//< 数据区长度，此处先保留该存储位置，稍后再对其进行存储
	Data1 = Data;
	MEMWRITE1(tmp_short);
	_iLen = (int)(_iLen - sizeof(tmp_short));

	//< 第三个数据为信息量，这个数据等打包完成后最后写入，此处先保留该存储位置，稍后再对其进行存储
	MEMWRITE1(SaveModel_Num[0]);
	_iLen = (int)(_iLen - sizeof(SaveModel_Num[0]));

	//< 写第二个数据
	tmp_short = (short)(_iLen - sizeof(Head) + sizeof(SaveModel_Num[0]));//< 等于目前已经计数的长度减去报头，加上要广播模块数量数据的长度
	MEMWRITE(tmp_short, Data1);

	//< 写第三个数据
	MEMWRITE(SaveModel_Num[0], Data1);

	//< 报尾
	MEMWRITE1(Tail);
	return _iLen;
#undef MEMWRITE1
}


//************************************
// Method:    	tBakAndRecvBak				主从备份线程
// Programmer:  lww
// Time:		2019/2/16
// Returns:   	void *
// Parameter: 	void * arg
//************************************
void *tBakAndRecvBak(void* arg)
{
#define PACK_MAXNUM	8
	int sock;
	static int Model_Total_Count = 0;
	struct sockaddr_in NetC;
	timer_t BakData_Timer;
	struct timespec time;
	short Head = 2601;				//< 报头
	short Tail = 3420;				//< 报尾
	char Data2Send[PACK_MAXNUM];	//< 存放数据包的数组
	int _iLen = 0;
	short masterrun = 20;
	short slaverun = 23;
	short slatomas = 24;
	pthread_t tPSS_ID = 0;
	//< 初始化UDP设置
	if (false == UDP_Init(&sock, BAKDATA_PORT, 0, 0, UDP_SEND_STATUS, nullptr)) { return 0; }

	//< 开启接收备份数据的线程
	THREAD_CREATE_FAILED(Thread_Create("tRecvBak_ID", &tPSS_ID, NULL, SCHED_POLICY, 89, true, tRecvPSS, CONTROL_CORE, NULL));

	//< 设置发送到的IP地址及端口
	Addr_Set(&NetC, BAKDATA_PORT, inet_addr(NETC_IP_BC));
	while (1)
	{
		if (SYS_Role == Master_Twins_Role||SYS_Role== Master_Alone_Role)
		{
			ExactDelay(200);
			_iLen = BakData_PACK_Make(Data2Send, Head, Tail,&masterrun);
			//< 发送数据
			if (-1 == UDP_Send(&sock, &NetC, (char*)Data2Send, _iLen))
				break;
		}
		else
			RoughDelay_S(2);
	}
	close(sock);//< 断开连接
#undef PACK_MAXNUM

}
